#pragma once
#include"Sem.hpp"
#include"Mutex.hpp"
#include<iostream>
#include<vector>

const int g_cap = 5;
using namespace SemMoudule;
using namespace MutexModule;

template<class T>
class RingQueue
{
public:
    RingQueue(int cap = g_cap)
    :_cap(cap),_rq(cap),_room_sem(cap),_data_sem(0)
    ,_p_step(0),_c_step(0)
    {

    }

    void Equeue(const T& in)
    {
        //生产者申请信号量
        _room_sem.P();
        _pmutex.Lock();
        _rq[_p_step] = in;
        ++_p_step;
        _p_step %= _cap;
        _data_sem.V();
    }

    void Pop(T* out)
    {
        //消费者申请信号量
        _data_sem.P();
        *out = _rq[_c_step];
        ++_c_step;
        _c_step %= _cap;
        _room_sem.V();
    }

    ~RingQueue(){}
    
private:
    std::vector<T> _rq;
    int _cap;
    Sem _room_sem;
    int _p_step;//下标

    Sem _data_sem;
    int _c_step;

    Mutex _pmutex;//维护多消费、多生产的两把锁
    Mutex _cmutex;
};
